﻿#region
/* ===============================================
 * 作者：guopeng           时间：2012/2/1 21:16:57
 * 
 * 
 * 类描述：用户基础类。提供用户的基础行为
 * 
 * =============================================== */
#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Jobs.Contact;
using Jobs.Inf.Entity;
using Jobs.Inf.DataContext;
using Jobs.Inf.Protector;

namespace Jobs.Domain.User
{
    public class User : Member
    {
        public User(string userName)
        {
            this.UserName = userName.ToLower();
            this.NickName = userName.ToLower();
        }

        /// <summary>
        /// 检测用户名是否已经存在
        /// </summary>
        /// <returns>0:不存在，可以使用 1：存在，不能使用</returns>
        public int CheckUserName()
        {
            using (Context ctx = new Context())
            {
                return ctx.Member.Any(c => c.UserName == this.UserName) ? 1 : 0;
            }
        }

        /// <summary>
        /// 新用户注册
        /// </summary>
        /// <param name="password">密码，使用AES进行加密</param>
        /// <param name="confirm">确认密码</param>
        /// <param name="nickname">昵称</param>
        /// <returns>0：失败 1：成功</returns>
        public bool Register(string password, string confirm)
        {
            if (String.IsNullOrEmpty(password) || password != confirm)
            {
                return false;
            }
            using (Context ctx = new Context())
            {
                try
                {
                    DateTime tokenDate = DateTime.Now;
                    var item = ctx.Member.Add(
                        new Member()
                        {
                            UserName = this.UserName,
                            Password = Inf.Function.AesAlgorithm.Encrypt(password),
                            IsActivate = false,
                            NickName = this.NickName,
                            Token = Inf.Function.HashAlgorithm.Encrypt(Guid.NewGuid().ToString(), Inf.Function.EncryptMode.sha1),
                            TokenDate = tokenDate
                        });
                    if (ctx.SaveChanges() > 0)
                    {
                        Jobs.Domain.Service.EMail email = new Service.EMail();
                        email.Send("注册激活邮件", this.UserName,
                            email.BuildWelcomeEmailBody(this.UserName, BuildFixToken(this.UserName, item.Token, tokenDate), tokenDate));
                    }
                }
                catch (Exception e)
                {
                    throw new RuntimeException("执行新用户注册时出错，错误为：\r\n{0}", e);
                }
                return true;
            }
        }

        /// <summary>
        /// 构建token值
        /// </summary>
        /// <param name="userName">用户名</param>
        /// <param name="token">Guid编码的token值</param>
        /// <param name="tokenDate">token的生成时间</param>
        /// <returns></returns>
        public string BuildFixToken(string userName, string token, DateTime tokenDate)
        {
            return Inf.Function.EncodeByBase64.Encode(String.Format("{0}*{1}*{2}", userName, token, tokenDate.ToString()));
        }
        
        /// <summary>
        /// 激活用户
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public static bool Activation(string token)
        {
            using (Context ctx = new Context())
            {
                string userName = string.Empty;
                if (ValidToken(token, ref userName))
                {
                    return ctx.Update<Inf.Entity.Member>()
                        .Set(c => c.IsActivate, true)
                        .WhereSet(c => c.UserName, WhereOperator.Equal, userName)
                        .End()
                        .Excute() > 0;
                }
            }
            return false;
        }
        /// <summary>
        /// 验证token
        /// </summary>
        /// <param name="token"></param>
        /// <param name="userName">token中包含的userName</param>
        /// <param name="tokenExpire">（单位：分钟，当值为0时不验证Token生成时间）Token的生成时间必须是当前时间的多少分钟之内</param>
        /// <returns></returns>
        public static bool ValidToken(string token,ref string userName, int tokenExpire = 0)
        {
            string source = Inf.Function.EncodeByBase64.Decode(token);
            string[] piece = source.Split('*');
            if (piece.Length < 3)
            {
                throw new Inf.Protector.RuntimeException("激活账号token码异常，接受到的token码为：" + token + "，解码后为：" +
                    source);
            }
            string _userName = piece[0];
            userName = _userName;
            using (Context ctx = new Context())
            {
                string dbTokent = piece[1];
                string tokentDate = piece[2];
                var item = ctx.Member.FirstOrDefault(c => c.UserName == _userName && c.Token == dbTokent);
                if (item == null) //用户名和token不匹配
                {
                    return false;
                }
                if (tokenExpire > 0) //需要验证token生成时间
                {
                    try
                    {
                        return item.TokenDate.AddMinutes(tokenExpire) >= DateTime.Parse(tokentDate);
                    }
                    catch (Exception)
                    {
                        return false;
                    }
                }
                return true;
            }
        }

        /// <summary>
        /// 用户登录
        /// </summary>
        /// <param name="validToken">一个0~1的小数</param>
        /// <param name="password">密码，需要使用AES加密进行比较</param>
        /// <param name="validCode">验证码</param>
        /// <returns>-1：验证码错误 0：用户名或密码错误 1：成功</returns>
        public int Login(string validToken, string password, string validCode)
        {
            //这里的验证码验证还没实现
            using (Context ctx = new Context())
            {
                var pwd = ctx.Member
                    .Where(c => c.UserName == this.UserName)
                    .Select(c=>c.Password)
                    .FirstOrDefault();
                if (!String.IsNullOrEmpty(pwd))
                {
                    return pwd == Inf.Function.AesAlgorithm.Encrypt(password) ? 1 : 0;
                }
            }
            return 0;
        }

        /// <summary>
        /// 邮箱找回密码
        /// </summary>
        /// <returns></returns>
        public int MailForResetPassword()
        {
            using (Context ctx = new Context())
            {
                string newToken = Inf.Function.HashAlgorithm.Encrypt(Guid.NewGuid().ToString(), Inf.Function.EncryptMode.sha1);
                DateTime tokenDate = DateTime.Now;
                ctx.Update<Inf.Entity.Member>()
                    .Set(c => c.Token, newToken)
                    .Set(c => c.TokenDate, tokenDate.ToString())
                    .WhereSet(c => c.UserName, WhereOperator.Equal, this.UserName)
                    .End()
                    .Excute();

                Jobs.Domain.Service.EMail email = new Service.EMail();
                email.Send("找回密码", this.UserName, email.BuildResetPasswordEmailBody(this.UserName, BuildFixToken(this.UserName, newToken, tokenDate), tokenDate));
            }
            return 1;
        }

        /// <summary>
        /// 重设密码，在重置之前请先验证token是否正确
        /// </summary>
        /// <param name="password"></param>
        /// <param name="confirm"></param>
        /// <returns></returns>
        public bool ResetPassword(string password, string confirm)
        {
            if (String.IsNullOrEmpty(password) || password != confirm)
            {
                return false;
            }
            using (Context ctx = new Context())
            {
                return ctx.Update<Inf.Entity.Member>()
                    .Set(c => c.Password, Inf.Function.AesAlgorithm.Encrypt(password))
                    .WhereSet(c => c.UserName, WhereOperator.Equal, this.UserName)
                    .End()
                    .Excute() > 0;
            }
        }
    }
}  
